package com.rybbaby.tss.platform.login.controller;
import com.rybbaby.tss.core.annotation.RequestLog;
import com.rybbaby.tss.core.annotation.Token;
import com.rybbaby.tss.core.utils.AjaxJsonResponse;
import com.rybbaby.tss.core.utils.PropertiesReadUtil;
import com.rybbaby.tss.core.utils.StringUtils;
import com.rybbaby.tss.core.web.controller.BaseController;
import com.rybbaby.tss.platform.initializer.MenuPermissionsInitializer;
import com.rybbaby.tss.platform.sysAdminUser.entity.SysAdminUser;
import com.rybbaby.tss.platform.sysAdminUser.service.ISysAdminUserService;
import com.rybbaby.tss.platform.sysAdminUserJoinSysRole.entity.SysAdminUserJoinSysRole;
import com.rybbaby.tss.platform.sysAdminUserJoinSysRole.service.ISysAdminUserJoinSysRoleService;
import com.rybbaby.tss.platform.sysMenuPermissions.entity.SysMenuPermissions;
import com.rybbaby.tss.platform.sysMenuPermissions.service.ISysMenuPermissionsService;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * @author 谢进伟
 * @description 系统管理员管理
 * @createDate 2016-1-30 上午9:45:12
 */
@Controller
@RequestMapping(value = "login")
public class LoginController extends BaseController {

    @Autowired
    private ISysAdminUserService sysAdminUserService;
    @Autowired
    private ISysAdminUserJoinSysRoleService sysAdminUserJoinSysRoleService;
    @Autowired
    private ISysMenuPermissionsService sysMenuPermissionsService;

    /**
     * 切换登录视图
     *
     * @return
     */
    @RequestMapping(value = "toLoginView")
    @RequestLog(content = "查看视图")
    public ModelAndView toLoginView() {
        String viewPath = PropertiesReadUtil.getStringProperty("lginView");
        ModelAndView mav = new ModelAndView(viewPath, request.getParameterMap());
        return mav;
    }

    /**
     * 登录系统
     *
     * @return
     */
    @RequestMapping(value = "checkLogin", method = RequestMethod.POST)
    @ResponseBody
    @RequestLog(content = "登录成功!")
    public String checkLogin() {
        AjaxJsonResponse ajr = new AjaxJsonResponse("已登录!");
        if (getLoginUser() == null) {
            ajr.setResCode(-1);
            ajr.setResMsg("未登录,请先登录!");
        }
        return ajr.jsonResponse(false);
    }

    /**
     * 退出系统
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "logout", method = RequestMethod.GET)
    @RequestLog(content = "退出系统", save = true)
    @ResponseBody
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        AjaxJsonResponse ajr = new AjaxJsonResponse("注销成功!");
        try {
            // 修改登录用户为离线状态
            Object loginUserId = getLoginUserId();
            if (loginUserId != null) {
                SysAdminUser loginUser = this.sysAdminUserService.get(loginUserId.toString());
                this.sysAdminUserService.offLine(loginUser);
            }
            // 注销Session
            boolean isSuccess = removeLoginUser();
            if (!isSuccess) {
                ajr.setResCode(500);
                ajr.setResMsg("登出失败,请稍后再试!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            ajr.setResCode(500);
            ajr.setResMsg("登出失败(" + e.getMessage() + "),请稍后再试!");

        }
        return ajr.jsonResponse(false);
    }

    /**
     * 登录系统
     *
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    @RequestLog(content = "登录成功!", save = true)
    @Token(validateToken = false)
    public String login() {
        AjaxJsonResponse ajr = new AjaxJsonResponse("登录成功!");
        try {
            String loginName = getParameter("userName");
            String password = getParameter("password");
            if (StringUtils.isBlank(loginName)) {
                ajr.setResCode(300);
                ajr.setResMsg("请输入登录名!");
            } else if (StringUtils.isBlank(password)) {
                ajr.setResCode(300);
                ajr.setResMsg("请输入登录密码!");
            } else {
                DetachedCriteria dc = DetachedCriteria.forClass(SysAdminUser.class);
                dc.add(Restrictions.or(Restrictions.eq("userName", loginName),Restrictions.eq("phoneNumber",loginName)));// 用户名
                List<SysAdminUser> users = this.sysAdminUserService.findByDetached(dc);
                if (users != null && !users.isEmpty()) {
                    SysAdminUser loginUser = users.get(0);
                    if (loginUser.getIsForbidden()) {
                        ajr.setResCode(-1);
                        ajr.setResMsg("您已被禁用,请联系管理员!");
                    } else {
                        SysAdminUser tempUser = new SysAdminUser();
                        tempUser.setId(loginUser.getId());
                        tempUser.setCreateTime(loginUser.getCreateTime());
                        tempUser.setUserPassword(password);
                        String encryptPassword = encryptPassword(tempUser);
                        if (!loginUser.getUserPassword().equals(encryptPassword)) {
                            ajr.setResCode(-1);
                            ajr.setResMsg("登录密码错误!");
                        } else {// 登录成功
                            // 修改用户状态为在线状态
                            this.sysAdminUserService.onLine(loginUser, getSession().getId());
                            // 用户拥有的角色
                            List<SysAdminUserJoinSysRole> joinSysRoles = this.sysAdminUserJoinSysRoleService.findByProperty("adminUserId", loginUser.getId());
                            // 缓存登录对象信息
                            super.cacheLoginUsr(loginUser, joinSysRoles);
                        }
                    }
                } else {
                    ajr.setResCode(-1);
                    ajr.setResMsg("用户名或密码错误!");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ajr.jsonResponse(true);
    }

    /**
     * 加载用户的菜单权限
     *
     * @param menusViewName 菜单视图名称,视图模板页面限制值 WEB-INF/views/common/menusView 文件夹内
     * @return
     */
    @RequestLog(content = "加载用户的菜单权限")
    @RequestMapping(value = "getMenuPermisssions", method = RequestMethod.GET)
    public ModelAndView getMenuPermisssions(String menusViewName) {
        String defaultMenusView = PropertiesReadUtil.getStringProperty("menusView", "common/menusView/defaultMenus.html");
        ModelAndView mav = new ModelAndView(StringUtils.isNotBlank(menusViewName) ? "common/menusView/" + menusViewName : defaultMenusView);
        try {
            // 加载登录用户所拥有的菜单权限
            Set<SysMenuPermissions> menuPermissions = loadMenuPermission(getLoginUser());
            mav.addObject("menuPermissions", menuPermissions);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mav;
    }

    /**
     * 加载登录用户所拥有的菜单权限
     *
     * @param loginUser 登录用户对象
     * @return
     * @throws Exception
     */
    private Set<SysMenuPermissions> loadMenuPermission(SysAdminUser loginUser) throws Exception {
        Set<SysMenuPermissions> topParents = new TreeSet<SysMenuPermissions>();
        try {
            // 加载登录用户所有的菜单权限
            List<SysMenuPermissions> loginUserHasSMP = this.sysMenuPermissionsService.getAdminUserMenuPermissions(loginUser.getId());
            // 加载所有菜单权限的父节点菜单权限
            Set<SysMenuPermissions> parents = new TreeSet<SysMenuPermissions>(new Comparator<SysMenuPermissions>() {

                @Override
                public int compare(SysMenuPermissions o1, SysMenuPermissions o2) {
                    return o1.getId().compareTo(o2.getId());
                }

            });
            for (SysMenuPermissions smp : loginUserHasSMP) {
                MenuPermissionsInitializer.getMenuTree(smp, parents);
            }
            // 将父菜单节点加入到用户拥有的菜单权限中
            loginUserHasSMP.addAll(parents);
            // 菜单节点的权重排序比较器
            Comparator<SysMenuPermissions> comparator = new Comparator<SysMenuPermissions>() {

                @Override
                public int compare(SysMenuPermissions o1, SysMenuPermissions o2) {
                    return o1.getWeight().compareTo(o2.getWeight());// 权重越大越往后排
                }

            };
            // 筛选出所有顶层菜单节点
            loginUserHasSMP.parallelStream().filter(new Predicate<SysMenuPermissions>() {

                @Override
                public boolean test(SysMenuPermissions t) {
                    return t.getpId() == null;
                }

            }).sorted(comparator).forEachOrdered(new Consumer<SysMenuPermissions>() {

                @Override
                public void accept(SysMenuPermissions t) {
                    topParents.add(t);
                }

            });
            // 正向筛选并设置所有顶层菜单节点的子菜单节点
            for (SysMenuPermissions psm : topParents) {
                setChildrenSmp(loginUserHasSMP, comparator, psm);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return topParents;
    }

    /**
     * 从菜单容器中筛选出指定菜单节点的子菜单节点
     *
     * @param loginUserHasSMP 菜单节点容器
     * @param comparator      排序比较器
     * @param psm             指定的节点
     */
    private void setChildrenSmp(List<SysMenuPermissions> loginUserHasSMP, Comparator<SysMenuPermissions> comparator, SysMenuPermissions psm) {
        loginUserHasSMP.parallelStream().filter(new Predicate<SysMenuPermissions>() {

            @Override
            public boolean test(SysMenuPermissions t) {
                return t.getpId() != null && t.getpId().equals(psm.getId());
            }

        }).sorted(comparator).forEachOrdered(new Consumer<SysMenuPermissions>() {

            @Override
            public void accept(SysMenuPermissions t) {
                psm.getChildrens().add(t);
                // 递归筛选
                setChildrenSmp(loginUserHasSMP, comparator, t);
            }

        });
    }
}
